<template>
  <div class="graph-container">
    <v-chart :option="chartOption" class="echart-instance" />
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted } from "vue";
import VChart from "vue-echarts";
import { use } from "echarts/core";
import { TreeChart } from "echarts/charts";
import { TooltipComponent, GridComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";

// 注册ECharts模块
use([TreeChart, TooltipComponent, GridComponent, CanvasRenderer]);

// 导入类型定义
import type { GraphNode, GraphEdge } from "./types";

// Props 定义
const props = defineProps<{
  nodes: GraphNode[];
  edges: GraphEdge[];
  // 可以在这里添加更多可配置的props，例如布局类型、颜色主题等
}>();

// ECharts 配置项
const chartOption = ref<any>({
  tooltip: {
    trigger: "item",
    formatter: (params: any) => {
      if (params.dataType === "node") {
        const node = params.data;
        let tooltipHtml = `<div style="padding: 8px;"><strong>${node.name}</strong>`;
        if (node.metadata) {
          Object.entries(node.metadata).forEach(([key, value]) => {
            if (value !== undefined) {
              tooltipHtml += `<div>${key}: ${value}</div>`;
            }
          });
        }
        tooltipHtml += "</div>";
        return tooltipHtml;
      } else if (params.dataType === "edge") {
        const edge = params.data;
        let tooltipHtml = `<div style="padding: 8px;"><strong>${edge.label}</strong>`;
        if (edge.metadata) {
          Object.entries(edge.metadata).forEach(([key, value]) => {
            if (value !== undefined) {
              tooltipHtml += `<div>${key}: ${value}</div>`;
            }
          });
        }
        tooltipHtml += "</div>";
        return tooltipHtml;
      }
      return params.name;
    },
    backgroundColor: "rgba(0, 0, 0, 0.7)",
    textStyle: { color: "#fff" },
    borderWidth: 0,
  },
  series: [
    {
      type: "tree",
      data: [], // 由props动态生成
      left: "10%",
      right: "10%",
      top: "10%",
      bottom: "10%",
      symbol: "rect",
      symbolSize: 80,
      orient: "LR", // 从上到下布局：TB (top-bottom), LR (left-right), RL (right-left), BT (bottom-top)
      roam: true, // 允许缩放和拖拽
      expandAndCollapse: true, // 允许展开和折叠
      initialTreeDepth: 3, // 初始展开深度
      label: {
        show: true,
        position: "inside",
        fontSize: 12,
        color: "#fff",
        fontWeight: "normal",
      },
      leaves: {
        // 叶子节点配置
        label: {
          show: true,
          position: "inside",
          fontSize: 12,
          color: "#fff",
        },
      },
      emphasis: {
        // 高亮配置
        focus: "descendant", // 聚焦到后代节点
      },
      lineStyle: {
        color: "#ccc",
        width: 2,
        curveness: 0, // 直线
      },
      itemStyle: {
        borderColor: "#fff",
        borderWidth: 1,
      },
    },
  ],
});

// 将图数据转换为树形结构
const transformToTree = () => {
  if (props.nodes.length === 0) {
    return null;
  }

  // 构建邻接表（子节点映射）
  const childrenMap = new Map<string, string[]>();
  const parentMap = new Map<string, string[]>();
  const nodeMap = new Map<string, GraphNode>();

  // 初始化
  props.nodes.forEach((node) => {
    nodeMap.set(node.id, node);
    childrenMap.set(node.id, []);
    parentMap.set(node.id, []);
  });

  // 构建边关系
  props.edges.forEach((edge) => {
    const children = childrenMap.get(edge.source) || [];
    children.push(edge.target);
    childrenMap.set(edge.source, children);

    const parents = parentMap.get(edge.target) || [];
    parents.push(edge.source);
    parentMap.set(edge.target, parents);
  });

  // 找到根节点（没有入边的节点）
  const rootNodes: string[] = [];
  props.nodes.forEach((node) => {
    const parents = parentMap.get(node.id) || [];
    if (parents.length === 0) {
      rootNodes.push(node.id);
    }
  });

  // 如果没有根节点（可能是环），选择第一个节点作为根
  if (rootNodes.length === 0 && props.nodes.length > 0) {
    rootNodes.push(props.nodes[0].id);
  }

  if (rootNodes.length === 0) {
    return null;
  }

  // 递归构建树节点
  const buildTreeNode = (nodeId: string, visited: Set<string>): any => {
    if (visited.has(nodeId)) {
      return null; // 避免循环引用
    }
    visited.add(nodeId);

    const node = nodeMap.get(nodeId);
    if (!node) return null;

    const children = childrenMap.get(nodeId) || [];
    const treeChildren: any[] = [];

    children.forEach((childId) => {
      const childNode = buildTreeNode(childId, visited);
      if (childNode) {
        treeChildren.push(childNode);
      }
    });

    return {
      name: node.label,
      value: node.id,
      itemStyle: {
        color: node.style.color,
        borderColor: "#fff",
        borderWidth: 1,
      },
      label: {
        show: true,
        fontSize: 12,
        color: "#fff",
      },
      symbolSize: node.style.size,
      children: treeChildren.length > 0 ? treeChildren : undefined,
      metadata: node.metadata,
      nodeType: node.type,
    };
  };

  // 如果有多个根节点，创建一个虚拟根节点
  if (rootNodes.length > 1) {
    const visited = new Set<string>();
    const children = rootNodes
      .map((rootId) => buildTreeNode(rootId, visited))
      .filter((node) => node !== null);

    return {
      name: "根节点",
      children: children,
    };
  } else {
    const visited = new Set<string>();
    return buildTreeNode(rootNodes[0], visited);
  }
};

// 更新图表数据
const updateChartData = () => {
  const treeData = transformToTree();
  if (treeData) {
    chartOption.value.series[0].data = [treeData];
  } else {
    chartOption.value.series[0].data = [];
  }
};

// 监听 props 变化，动态更新图表
watch(
  () => [props.nodes, props.edges],
  () => {
    updateChartData();
  },
  { deep: true, immediate: true } // 深度监听，立即执行一次
);

// 组件挂载时初始化图表
onMounted(() => {
  updateChartData();
});
</script>

<style scoped>
.graph-container {
  width: 100%;
  height: 100%;
  min-height: 600px;
  border: 1px solid #ebeef5;
  border-radius: 8px;
  background-color: #f9f9f9;
}
.echart-instance {
  width: 100%;
  height: 100%;
  min-height: 600px;
}
</style>
